<?php

/* ----------------------------------------------
  Caloris: Core Member Class

  $Id$
  $Author$

 * Třídy Caloris
 * 
  ---------------------------------------------- */

namespace Caloris {

    // IO: Práce se soubory a adresáři

    class IO {

        // Uploads file.

        public static function upload($pathDirectory, $fileName, $chmod = 0777) {
            $path = $pathDirectory . '/' . $fileName;

            if (file_exists($path)) {
                return false;
            } elseif ($_FILES['the_file']['tmp_name'] == "") {
                return false;
            } else {
                copy($_FILES["the_file"]["tmp_name"], $path);
                chmod($path, $chmod);
                return true;
            }
        }

        // Remove file or directory

        public static function remove($fileName) {
            if (file_exists($fileName)) {

                if (is_dir($fileName)) {
                    rmdir($fileName);
                } else {
                    unlink($fileName);
                }
            }
        }

        // Reads files. When 1 is set to highlight parameter, Caloris extensions syntax is highlighted

        public static function get($path) {
            $fileHandle = fopen($path, "r");

            if (file_exists($path) && filesize($path) > 0) {
                $typer = fread($fileHandle, filesize($path));
            }

            fclose($fileHandle);

            return $typer;
        }

        // Creates directory and sets user rights.

        public static function directoryMake($path, $chmod = 0777) {
            \Caloris\ACL::authenticate();

            if (!file_exists($path)) {
                $oldUmask = umask(0);
                mkdir($path, $chmod);
                chmod($path, $chmod);
                umask($oldUmask);
            }
        }

        // Renames files or moves to a different directory.

        public static function rename($pathFrom, $pathTo) {
            if (!file_exists($pathFrom) && file_exists($pathTo)) {
                rename($pathFrom, $pathTo);
            }
        }

    }

    // TIME - třída pro práci s daty

    class Time {

        public static function dateDifference($interval, $datefrom, $dateto, $using_timestamps = false) {
            /*
              $interval can be:
              yyyy - počet celých let, q - počet celých čtvrtletí
              m - počet celých měsíců, y - rozdíl mezi čísly dnů
              (např. 1st Jan 2004 is "1", the first day. 2nd Feb 2003 is "33".
              The datediff is "-32".)
              d - počet celých dnů, w - počet celých víkendů, ww - počet celých týdnů, h - počet celých hodin
              n - počet celých minut, s - počet celých sekund (defaultně)
             */

            if (!$using_timestamps) {
                $datefrom = strtotime($datefrom, 0);
                $dateto = strtotime($dateto, 0);
            }
            $difference = $dateto - $datefrom; // Difference in seconds

            switch ($interval) {
                case 'yyyy': // number of full years
                    $years_difference = floor($difference / 31536000);
                    if (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom), date("j", $datefrom), date("Y", $datefrom) + $years_difference) > $dateto) {

                        $years_difference--;
                    }
                    if (mktime(date("H", $dateto), date("i", $dateto), date("s", $dateto), date("n", $dateto), date("j", $dateto), date("Y", $dateto) - ($years_difference + 1)) > $datefrom) {

                        $years_difference++;
                    }
                    $datediff = $years_difference;
                    break;

                case "q": // number of full quarters
                    $quarters_difference = floor($difference / 8035200);
                    while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom) + ($quarters_difference * 3), date("j", $dateto), date("Y", $datefrom)) < $dateto) {

                        $months_difference++;
                    }
                    $quarters_difference--;
                    $datediff = $quarters_difference;
                    break;

                case "m": // number of  full months
                    $months_difference = floor($difference / 2678400);
                    while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom) + ($months_difference), date("j", $dateto), date("Y", $datefrom)) == 7) { // Sunday
                        $days_remainder--;
                    }
                    if ($odd_days > 6) { // Saturday
                        $days_remainder--;
                    }
                    $datediff = ($weeks_difference * 5) + $days_remainder;
                    break;

                case "ww": // number of full weeks
                    $datediff = floor($difference / 604800);
                    break;

                case "h": // number of full hours
                    $datediff = floor($difference / 3600);
                    break;

                case "n": // number of full minutes
                    $datediff = floor($difference / 60);
                    break;

                default: // number of full seconds (default)
                    $datediff = $difference;
                    break;
            }

            return $datediff;
        }

    }

    // TOOLS - jednoduché nezařaditelné funkce

    class Tools {

        // Answerio: Vypisuje radio buttony s ano a ne a nastaveno val_ hodnotou
        public static function answerio($input, $val) {
            if (is_numeric($val) == false) {
                $nval = '';
            } else {
                $nval = 'val_';
            }

            if ($input == 1) {
                $content = '<input type="radio" name="' . $nval . $val . '" value="1" checked="checked" /> ano <input type="radio" name="' . $nval . $val . '" value="0" /> ne';
            } else {
                $content = '<input type="radio" name="' . $nval . $val . '" value="1" /> ano <input type="radio" name="' . $nval . $val . '" value="0" checked="checked" /> ne';
            }

            return $content;
        }

        // Geterror: Vypíše chybové hlášení is se styly
        function getError($nr, $title, $description) {
            return '
<html>
<head>
	<title>' . $title . '</title>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
	<style>p {margin: 0;} body {font-family: sans-serif; font-size: 0.94em;}</style>
</head>
<body>
<div style="border: 1px solid #ddd; background-color: #fafafa; padding: 10px 10px; ">
<h1 style="font-size: 14px; padding: 0; margin: 10px 0;">' . $title . '</h1>
<p style="font-size: 12px;">' . $description . '</p>

<table style="margin: 10px 0;">
    <tr>
        <td style="font-size: 10px;">Kód chyby:</td>
        <td style="font-size: 10px; padding-left: 10px;"><strong>' . $nr . '</strong></td>
    </tr>
    <tr>
        <td style="font-size: 10px;">Soubor:</td>
        <td style="font-size: 10px; padding-left: 10px;"><strong>' . $_SERVER["PHP_SELF"] . '</strong></td>
    </tr>
    <tr>
        <td style="font-size: 10px;">Server:</td>
        <td style="font-size: 10px; padding-left: 10px;"><strong>' . $_SERVER["HTTP_HOST"] . '</strong></td>
    </tr>
</table>

<p style="font-size: 9px;">Web běží na systému Caloris ' . _CALSET_CALORIS_VERSION_MINOR . '</p>
</div>
</body>
</html>' . PHP_EOL;
        }

        // checknull: If value is null returns 0
        public static function checknull($data) {
            if ($data == '') {
                return 0;
            } else {
                return $data;
            }
        }

    }

    // TEXT - Class for work with text

    class Text {

        public static function protect($protect) {

            $content = Str_Replace(Array("<", ">", "*", ";", "\"", "'", "`", "=", "DELETE", "delete", "DROP", "drop", "INSERT", "insert", "UPDATE", "update"), Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""), $protect);

            return $content;
        }

        public static function wordLimit($text, $limit = 100, $chars = 'áýéíóúůěřčžšďťňÚŮŤÁÉĎŇŠČŘ+0123456789®<>="/ü™ł–&.),(„“') {

            $text = strip_tags($text);

            if (strlen($text) > $limit) {
                $words = str_word_count($text, 2, $chars);
                $words = array_reverse($words, TRUE);
                foreach ($words as $length => $word) {
                    if ($length + strlen($word) >= $limit) {
                        array_shift($words);
                    } else {
                        break;
                    }
                }
                $words = array_reverse($words);
                $text = implode(" ", $words) . '&hellip;';
            }
            return $text;
        }

        public static function caltag($string) {
            $string = preg_replace("/\[/", '&#91;', $string);
            $tcont2 = preg_replace("/\</", '&lt;', $string);
            $tcont2 = preg_replace("/\>/", '&gt;', $tcont2);
            $tcont2 = preg_replace("/\=/", '&#61;', $tcont2);
            $tcont2 = preg_replace("/\"/", '&#34;', $tcont2);
            $string = preg_replace("/\>/", '&gt;', $tcont2);

            return $string;
        }

        public static function highlight($content) {

            $content = preg_replace("/\&\#91;cal:([a-z_]+).\/([^]]*)\]/i", '<span style="color: red;">$0</span>', $content);
            $content = preg_replace("/\&\#91;cal:([a-z_]+)([^\]]*)\]/i", '<span style="color: red;">$0</span>', $content);
            $content = preg_replace("/\&\#91;\/cal:([a-z_]+)\]/i", '<span style="color: red;">$0</span>', $content);


            return $content;
        }

    }

    // DATABASE - class for work with database, DEPRECATED, use Nette\Database\Connection

    class Database {

        var $max;

        // Connection string
        function connect($type = _CALSET_DATABASE_TYPE, $ip = _CALSET_DATABASE_ADDRESS, $dbname = _CALSET_DATABASE_NAME, $username = _CALSET_DATABASE_USER, $password = _CALSET_DATABASE_PASSWORD, $port = _CALSET_DATABASE_PORT) {
            $this->type = $type;
            $this->dbname = $dbname;

            if ($type == 'mysql') {
                $constring = "mysql:host=$ip;dbname=$dbname";
            }

            $this->constring = $constring;
            $this->username = $username;
            $this->password = $password;

            $this->connect = '';

            return $this->connect;
        }

        function set($limit = 20) { // rename to page-size
            $this->connect();

            if (!isset($_GET["page"])) {
                $page = 1;
            } else {
                $page = $_GET["page"];
            }

            $this->limit = $limit;
            $this->page_actual = $page;
            $this->script = basename($_SERVER["PHP_SELF"], "/");
            $this->offset = ($page * $this->limit) - $this->limit;
        }

        function rows() {
            return $this->rows;
        }

        function query($sql = '') {
            if ($this->limit == '') {
                $this->set('n');
            }

            $this->sql_raw = $sql;

            // Converts from <||> to ``
            $sql = Str_Replace(Array("<|", "|>", " ILIKE "), Array("`", "`", " LIKE "), $this->sql_raw);

            // Limit, offset
            if (is_numeric($this->limit)) {
                $sql_suffix = " LIMIT " . $this->limit . " OFFSET " . $this->offset;
            } else {
                $sql_suffix = '';
            }

            //$dbh->arrayopt = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8");
            $dbh = new \PDO($this->constring, $this->username, $this->password, array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));


            // Saving result to array
            $sth = $dbh->prepare($sql . $sql_suffix);
            $sth->execute();

            $this->sql = $sql;
            $this->sqlarray = $sth->fetchAll();
            $this->rows = count($this->sqlarray);
        }

        function rowst() {
            $dbr = new \PDO($this->constring, $this->username, $this->password, array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
            $stc = $dbr->prepare("SELECT count(*) AS allc FROM (" . $this->sql . ") AS tblc");
            $stc->execute();
            $max = $stc->fetchAll();

            return $max[0][0];
        }

        function paging($range, $pagequery = '') {
            if (self::rowst() > $this->limit) {
                $pself = $this->uri;
                $pagequery = $this->querystring;

                $pselfpos = strchr($pself, "/"); // name of the page

                $pgtotal = ceil(self::rowst() / $this->limit); // number of pages
                $istart = ceil($this->page_actual - ($range / 2));
                $iend = floor($this->page_actual + ($range / 2));
                $this->total = $pgtotal;

                if ($pgtotal > $range) {

                    if ($istart < ($range / 2)) {
                        $istart = 1;
                        $iend = $range;
                    }

                    if ($iend > $pgtotal) {
                        $istart = ($pgtotal - $range);
                        $iend = $pgtotal;
                    }
                } else {
                    $istart = 1;
                    $iend = $pgtotal;
                }

                if ($pgtotal > 1) {
                    $c = -1;
                    for ($i = $istart; $i < ($iend + 1); $i++) {
                        $c = $c + 1;
                        if ($this->page_actual == $i) {
                            if ($i == $iend) {
                                $pgres[$c] = '<span class="paging active">' . $i . '</span>';
                            } else {
                                $pgres[$c] = '<span class="paging active">' . $i . '</span>';
                            }
                        } else {
                            if ($i == $iend) {
                                $pgres[$c] = '<span class="paging"><a href="' . substr($pself, $pselfpos) . '?page=' . $i . $pagequery . '">' . $i . '</a></span>';
                            } else {
                                $pgres[$c] = '<span class="paging"><a href="' . substr($pself, $pselfpos) . '?page=' . $i . $pagequery . '">' . $i . '</a></span>';
                            }
                        }
                    }
                }

                return $pgres;
            } else {
                return self::rowst();
            }
        }

        function show_rows() {
            if ($this->rowst() == 1) {
                $recs = _CALSET_DATABASE_TEXT_RECORD;
            } else {
                $recs = _CALSET_DATABASE_TEXT_RECORDS;
            }

            if (_CALSET_DATABASE_TEXT_RECORD_POSITION == 'before') {
                $text = $recs . $this->rowst();
            } else {
                $text = $this->rowst() . $recs;
            }

            return $text;
        }

        function show_paging($pageCount = 8) {
            if (count($this->paging($pageCount)) > 1) {
                $pagprods = $this->paging($pageCount);

                for ($n = 0; $n < count($pagprods); $n++) {
                    $pag .= $pagprods[$n];
                }

                if ($this->page_actual != 1) {
                    $pagin .= '<span class="paging"><a href="' . $this->uri . '?page=1' . $this->querystring . '">' . _CALSET_DATABASE_TEXT_FIRST . '</a></span>';
                    $pagin .= '<span class="paging"><a href="' . $this->uri . '?page=' . ($this->page_actual - 1) . $this->querystring . '">' . _CALSET_DATABASE_TEXT_PREV . '</a></span>';
                }

                $pagin .= $pag;

                if ($this->page_actual != $this->total) {
                    $pagin .= '<span class="paging"><a href="' . $this->uri . '?page=' . ($this->page_actual + 1) . $this->querystring . '">' . _CALSET_DATABASE_TEXT_NEXT . '</a></span>';
                    $pagin .= '<span class="paging"><a href="' . $this->uri . '?page=' . $this->total . $this->querystring . '">' . _CALSET_DATABASE_TEXT_LAST . '</a></span>';
                }

                $pagin .= PHP_EOL . '               <div style="clear: both;"></div>';
            }

            return $pagin; //Total rows in table
        }

        function cell($row, $column) {
            $sqlarray = $this->sqlarray;

            return $sqlarray[$row][$column];
        }

        function debug() {
            return '
<table style="margin-top: 20px" border="1">
	<tr>
		<td style="padding: 2px 5px;">Query without <||></td>
		<td style="padding: 2px 5px; padding-left: 10px;">' . $this->sql_raw . '</td>
	</tr>
	<tr>
		<td style="padding: 2px 5px;">Query</td>
		<td style="padding: 2px 5px; padding-left: 10px;">' . $this->sql . '</td>
	</tr>
	<tr>
		<td style="padding: 2px 5px;">Total Rows</td>
		<td style="padding: 2px 5px; padding-left: 10px;">' . $this->rowst() . '</td>
	</tr>
	<tr>
		<td style="padding: 2px 5px;">Affected rows</td>
		<td style="padding: 2px 5px; padding-left: 10px;">' . $this->rows . '</td>
	</tr>
</table>';
        }

        // Nová část

        function uri($uri = '') {
            if (empty($uri)) {
                $ruri = $_SERVER["REQUEST_URI"];
                $sname = $_SERVER["SCRIPT_NAME"];
            } else {
                $ruri = $uri;
                $sname = $uri;
            }

            if ($_GET["rewritetype"] == 1) {
                $qpos = strpos($ruri, "?");
                $pself = substr($ruri, 0, $qpos);
                $qq = '?';
            } else {
                $pself = $sname;
                $qq = '?';

                if (_CALSET_BASIC_MOD_REWRITE == 0 or file_exists(_CALSET_PATHS_BASE . '/.htaccess') == false) {
                    $pself = $sname . '?ctemplate=' . $_REQUEST["ctemplate"];
                    $qq = '&amp;';
                }
            }

            $this->uri = $pself;
        }

        function querystring($pagequery = '') {
            $this->querystring = '&amp;' . $pagequery;
        }

    }

    // ACL - access control list, member management and permission management

    class ACL {

        public static function authenticate() {
            $type = 'admin';
            $auser = $_COOKIE["auser"];
            $apwd = $_COOKIE["apwd"];

            // Checks for the existence of user
            $xmlUser = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/users.xml');
            $xmlUserEdit = $xmlUser->xpath('//user[@id="' . $auser . '"]');

            if (count($xmlUserEdit) == 0) {
                if ($type == 'admin') {
                    header('Location: ' . _CALSET_PATHS_URI . _CALSET_DIRS_ADMIN . '/login.php?msg=' . urlencode('Zadali jste chybné uživatelské jméno'));
                } else {
                    header('Location: ' . ln('login', '', 'msg=' . urlencode("Zadali jste chybné heslo")));
                }
            }

            if ($xmlUserEdit[0]->password <> $apwd) {
                if ($type == 'admin') {
                    header('Location: ' . _CALSET_PATHS_URI . _CALSET_DIRS_ADMIN . '/login.php?msg=' . urlencode('Zadali jste chybné heslo'));
                } else {
                    header('Location: ' . ln('login', '', 'msg=' . urlencode("Zadali jste chybné heslo")));
                }
                exit();
            }

            // If non-admin account, get error message
            if ($type == 'admin' && $xmlUserEdit[0]["admin"] == 0) {
                header('Location: ' . _CALSET_PATHS_URI . _CALSET_DIRS_ADMIN . '/login.php?msg=' . urlencode('Zadali jste chybné heslo'));
                exit();
            }

            // Blocked account
            if ($xmlUserEdit[0]->state->permissions == 0) {
                if ($type == 'admin') {
                    header('Location: ' . _CALSET_PATHS_URI . _CALSET_DIRS_ADMIN . '/login.php?msg=' . urlencode('Váš účet byl zablokován'));
                } else {
                    header('Location: ' . ln('login', '', 'msg=' . urlencode("Váš účet byl zablokován")));
                }
                exit();
            }

            $xmlUserEdit[0]->date->visited = date("Y-m-d H:i:s");
            $xmlUser->asXML(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/users.xml');
        }

        public static function authorize($type) {
            $xmlUser = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/users.xml');
            $xmlUserEdit = $xmlUser->xpath('//user[@id="' . $_COOKIE["auser"] . '"]');

            if (count($xmlUserEdit) > 0) {
                // Loads permissions from XML file
                $xml = simplexml_load_file(_CALSET_PATHS_BASE . '/cal-components/data/permissions.xml');
                $resultPermission = $xml->xpath('//permission[@id="' . $xmlUserEdit[0]->state->permissions . '"]');

                $content = $resultPermission[0]->types->{$type};
            } else {
                $content = 0;
            }

            return $content;
        }

        public static function passCheck($pwd) {
            preg_match("/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-]{6,40}$/", $pwd) ? $return = true : $return = false;

            return $return;
        }

        public static function passHash($password) {
            $salt = substr(md5($password), 0, 2);
            $password = md5($salt . $password) . ':' . $salt;

            return $password;
        }

    }

    // XML - Class for working with XML files

    class XML {

        // Retrieves data from file and converts them to object

        function source($fileName) {
            if (file_exists($fileName)) {
                $this->output = simplexml_load_file($fileName);
                $this->count = count($this->output);
                return $this->output;
            }
        }

        function count() {
            return $this->count;
        }

        function filter($xpath, $limit = 0) {
            $this->limit = $limit;

            if ($this->limit > 0) {
                $this->page = $_REQUEST["page"];

                if ($this->page == '') {
                    $this->page = 1;
                }


                $positionStart = ($limit * $this->page) - $limit;
                $positionEnd = ($limit * $this->page) + 1;

                $limitXPath = '[position() > ' . $positionStart . ' and position() < ' . $positionEnd . ']';
            } else {
                $limitXPath = '';
            }

            $object = $this->output;
            $this->output = $object->xpath($xpath . $limitXPath);

            return $this->output;
        }

        function output() {
            return $this->output;
        }

        function paging() {
            $pageTotal = ceil($this->count / $this->limit);

            if (isset($this->uri)) {
                $uri = $this->uri;
            } else {
                $uri = '';
            }

            if (isset($this->querystring)) {
                $querystring = $this->querystring;
            } else {
                $querystring = '';
            }

            $content = '';

            if ($this->page != 1) {
                $content .= '<span><a href="' . $uri . '?page=1' . $querystring . '">' . _CALSET_DATABASE_TEXT_FIRST . '</a> </span>';
                $content .= '<span><a href="' . $uri . '?page=' . ($this->page - 1) . $querystring . '">' . _CALSET_DATABASE_TEXT_PREV . '</a> </span>';
            }

            for ($a = 0; $a < $pageTotal; $a++) {
                $content .= '<a href="' . $uri . '?page=' . ($a + 1) . $querystring . '">' . ($a + 1) . '</a> | ';
            }

            $content = substr($content, 0, -3);

            if ($this->page != $this->count) {
                $content .= '<span> <a href="' . $uri . '?page=' . ($this->page + 1) . $querystring . '">' . _CALSET_DATABASE_TEXT_NEXT . '</a></span>';
                $content .= '<span> <a href="' . $uri . '?page=' . $pageTotal . $querystring . '">' . _CALSET_DATABASE_TEXT_LAST . '</a></span>';
            }

            $content = '<div>' . $content . '</div>';

            return $content;
        }

        function uri($uri = '') {
            if (empty($uri)) {
                $ruri = $_SERVER["REQUEST_URI"];
                $sname = $_SERVER["SCRIPT_NAME"];
            } else {
                $ruri = $uri;
                $sname = $uri;
            }

            if ($_GET["rewritetype"] == 1) {
                $qpos = strpos($ruri, "?");
                $pself = substr($ruri, 0, $qpos);
                $qq = '?';
            } else {
                $pself = $sname;
                $qq = '?';

                if (_CALSET_BASIC_MOD_REWRITE == 0 or file_exists(_CALSET_PATHS_BASE . '/.htaccess') == false) {
                    $pself = $sname . '?ctemplate=' . $_REQUEST["ctemplate"];
                    $qq = '&amp;';
                }
            }

            $this->uri = $pself; // Page uri for links
        }

        function querystring($pagequery = '') {
            $this->querystring = '&amp;' . $pagequery; // Querystring for every link
        }

    }

    // TEMPLATE - templating engine

    class Template {

        function input($content, $type = '') {
            if ($content == '') {
                if ($_REQUEST["ctemplate"] != '') {
                    $content = $_GET["ctemplate"];
                } else {
                    $content = 'index';
                }
            }

            if ($type == 'xml') {
                if (file_exists(_CALSET_PATHS_BASE . _CALSET_DIRS_PAGES . '/' . $content . '.html')) {
                    $xmr = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/pages.xml');
                    $xmp = $xmr->xpath('//page[@id="' . $content . '"]');

                    if ($xmp[0]->enable == 1) {
                        $contentPage = file_get_contents(_CALSET_PATHS_BASE . _CALSET_DIRS_PAGES . '/' . $content . '.html');

                        $this->name = $content;
                        $this->type = 'xml';
                        $this->content = $contentPage;
                    } else {
                        echo \Caloris\Tools::getError('005', 'Chyba', 'Chybový soubor nepovolen');
                    }
                } else {
                    if (_CALSET_PATHS_BASE == '') {
                        echo \Caloris\Tools::getError('006', 'Chyba', 'Neexistuje cesta k šabloně souboru');
                    } else {
                        if ($content == 'p404') {
                            header('Location: ' . _CALSET_PATHS_URI . 'index.php?ctemplate=p404');
                            exit();
                        }
                    }
                }
            } else {
                if (is_array($content)) {
                    $this->content = $content[0];

                    if (isset($content[1])) {
                        $this->content2 = $content[1];
                    }
                } else {
                    $this->content = $content;
                }
                $this->type = 'string';
            }
        }

        public function parse($content) {
            $content = preg_replace('/\n\r\t/s', ' ', $content);
            $content = preg_replace('/\[+(?!cal)/s', '&#91\;', $content);

            // Converts empty cal tags
            preg_match_all("/\[cal:([a-z\-_]+).\/([^]]*)\]/s", $content, $valsimp, PREG_SET_ORDER);

            if (count($valsimp) > 0) {
                for ($n = 0; $n < count($valsimp); $n++) {
                    $extensionName = substr($valsimp[$n][1], 0);

                    if (function_exists($extensionName) == false) {
                        include_once(_CALSET_PATHS_BASE . _CALSET_DIRS_EXTENSION . "/" . $extensionName . ".php");
                    }

                    $results = call_user_func($extensionName);
                    $content = str_replace($valsimp[$n][0], "$results", $content);
                }
            }

            $x = 1;
            // Converts non-pair tags with argument: new revoutionized version

            do {
                $x = $x + 1;
                preg_match_all("/\[cal:([a-z\-_^\(]+)\((.[^[]*?)\) \/\]/s", $content, $valfind2, PREG_SET_ORDER);

                for ($e = 0; $e < count($valfind2); $e++) {
                    $tagname3 = substr($valfind2[$e][1], 0);
                    if (file_exists(_CALSET_PATHS_BASE . _CALSET_DIRS_EXTENSION . "/" . $tagname3 . ".php") || function_exists($tagname3) == true) {
                        if (function_exists($tagname3) == false) {
                            include_once(_CALSET_PATHS_BASE . _CALSET_DIRS_EXTENSION . "/" . $tagname3 . ".php");
                        }

                        if (function_exists($tagname3)) {
                            $tagname3 = substr($valfind2[$e][1], 0);
                            $params3 = $valfind2[$e][2];
                            $paramSplit = preg_split('/(?<!\\\);/', $params3);

                            $results = call_user_func_array($tagname3, $paramSplit);
                            $content = str_replace($valfind2[$e][0], "$results", $content);

                            unset($results, $tagname3, $paramSplit);
                        }
                    }
                }
            } while ($x < 4/* strpos($content, '[cal:') > 0 */);

            $content = Str_Replace('&#91\;', '[', $content);

            return $content;
        }

        function loadTemplate($template = 'caloris-basic') {
            $xml = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_TEMPLATE . '/' . $template . '/basic.xml');

            $content = $xml->schema;

            preg_match_all('/\[cal:[a-zA-Z0-9\s\="\.]{1,}\]/s', $content, $subjectx, PREG_PATTERN_ORDER);

            for ($a = 0; $a < count($subjectx[0]); $a++) {
                $navigationResult = $xml->xpath('//navigation[@id="' . substr($subjectx[0][$a], 5, -1) . '"]');

                $content = str_replace($subjectx[0][$a], $navigationResult[0]->content, $content);
            }

            return $content;
        }

        function headTags($dbtag, $xmltag, $startag, $endtag) {
            if (strlen($dbtag) == 0) {
                if (strlen($xmltag) == 0) {
                    $content = '';
                } else {
                    $xmltagi = explode(';', $xmltag);
                    if (count($xmltagi) > 1) {
                        for ($a = 0; $a < count($xmltagi); $a++) {
                            $content .= '	' . $startag . $xmltagi[$a] . $endtag . '
';
                        }
                    } else {
                        $content = '	' . $startag . $xmltag . $endtag . '
';
                    }
                }
            } else {
                $dbtagi = explode(';', $dbtag);

                if (count($dbtagi) > 1) {
                    for ($a = 0; $a < count($dbtagi); $a++) {
                        $content .= '	' . $startag . $dbtagi[$a] . $endtag . '
';
                    }
                } else {
                    $content = '	' . $startag . $dbtag . $endtag . '
';
                }
            }

            return $content;
        }

        function renderHead($data = '') {
            $head = '';
            if (file_exists(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/pages.xml')) {
                $xmr = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_DATA . '/pages.xml');

                if (isset($this->name)) {
                    $xml = $xmr->xpath('//page[@id="' . $this->name . '"]');
                } else {
                    $xml = $xmr->xpath('//page[@id=""]');
                }
            }

            if ($this->type == 'xml') {
                if (file_exists(_CALSET_PATHS_BASE . _CALSET_DIRS_TEMPLATE . '/' . _CALSET_BASIC_TEMPLATE . '/basic.xml')) {
                    $xmb = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_TEMPLATE . '/' . _CALSET_BASIC_TEMPLATE . '/basic.xml');
                }

                // Loads external styles
                if (count($xml[0]->style->files) == 0 || $xml[0]->style["type"] == 'follow' || count($xml[0]->style->files[1]) == '') {
                    for ($a = 0; $a < count($xmb->data->style->files); $a++) {
                        if (substr($xmb->data->style->files[$a], 0, 7) == 'http://') {
                            $head .= '  <link rel="stylesheet" href="' . $xmb->data->style->files[$a] . '" type="text/css" media="screen,projection" />
';
                        } else {
                            $head .= '  <link rel="stylesheet" href="' . _CALSET_PATHS_URI . _CALSET_DIRS_TEMPLATE . '/' . _CALSET_BASIC_TEMPLATE . '/' . $xmb->data->style->files[$a] . '" type="text/css" media="screen,projection" />' . PHP_EOL;
                        }
                    }
                }

                if (count($xml[0]->style->files) > 0) {
                    for ($a = 0; $a < count($xml[0]->style->files); $a++) {
                        if (substr($xml[0]->style->files[$a], 0, 7) == 'http://' && $xml[0]->style->files[$a] != '') {
                            $head .= '  <link rel="stylesheet" href="' . $xml[0]->style->files[$a] . '" type="text/css" media="screen,projection" test />' . PHP_EOL;
                        } elseif ($xml[0]->style->files[$a] != '') {
                            $head .= '  <link rel="stylesheet" href="' . _CALSET_PATHS_URI . _CALSET_DIRS_TEMPLATE . '/' . _CALSET_BASIC_TEMPLATE . '/' . $xml[0]->style->files[$a] . '" type="text/css" media="screen,projection" />' . PHP_EOL;
                        }
                    }
                }

                // Loads external scripts
                if (count($xml[0]->scripts->files) == 0 || $xml[0]->scripts["type"] == 'follow' || count($xml[0]->scripts->files[1]) == '') {
                    for ($a = 0; $a < count($xmb->data->scripts->files); $a++) {
                        if (substr($xmb->data->scripts->files[$a], 0, 7) == 'http://') {
                            $head .= '  <script src="' . $xmb->data->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        } else {
                            $head .= '  <script src="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $xmb->data->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        }
                    }
                }

                if (count($xml[0]->scripts->files) > 0 || count($xml[0]->scripts->files[1]) == '') {
                    for ($a = 0; $a < count($xml[0]->scripts->files); $a++) {
                        if (substr($xml[0]->scripts->files[$a], 0, 7) == 'http://' && $xml[0]->scripts->files[$a] != '') {
                            $head .= '  <script src="' . $xml[0]->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        } elseif ($xml[0]->scripts->files[$a] != '') {
                            $head .= '  <script src="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $xml[0]->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        }
                    }
                }

                // Loads RSS feed
                if (count($xml[0]->rss->files) == 0 || $xml[0]->rss["type"] == 'follow') {
                    for ($a = 0; $a < count($xmb->data->rss->files); $a++) {
                        if (substr($xmb->data->rss->files[$a], 0, 7) == 'http://') {
                            $head .= '  <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="' . $xmb->data->rss->files[$a] . '" />' . PHP_EOL;
                        } else {
                            $head .= '  <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $xmb->data->rss->files[$a] . '" />' . PHP_EOL;
                        }
                    }
                }

                if (count($xml[0]->rss->files) > 0) {
                    for ($a = 0; $a < count($xml[0]->rss->files); $a++) {
                        if (substr($xml[0]->rss->files[$a], 0, 7) == 'http://' && $xml[0]->rss->files[$a] != '') {
                            $head .= '  <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="' . $xml[0]->rss->files[$a] . '" />' . PHP_EOL;
                        } elseif ($xml[0]->rss->files[$a] != '') {
                            $head .= '  <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $xml[0]->rss->files[$a] . '" />' . PHP_EOL;
                        }
                    }
                }

                // Page title
                if ($xml[0]->title == '') {
                    $head .= '  <title>' . $xmb->data->title->prefix . $xmb->data->title->name . $xmb->data->title->suffix . '</title>' . PHP_EOL;
                } else {
                    $head .= '  <title>' . $xmb->data->title->prefix . $xml[0]->title . $xmb->data->title->suffix . '</title>' . PHP_EOL;
                }

                // Meta descriptions
                if ($xml[0]->meta->description == '' && $xmb->data->meta->description == '') {
                    $head .= '';
                } elseif ($xml[0]->meta->description == '') {
                    $head .= '  <meta name="description" content="' . $xmb->data->meta->description . '" />' . PHP_EOL;
                } else {
                    $head .= '  <meta name="description" content="' . $xml[0]->meta->description . '" />' . PHP_EOL;
                }

                // Meta keywords
                if ($xml[0]->meta->keywords == '' && $xmb->data->meta->keywords == '') {
                    $head .= '';
                } elseif ($xml[0]->meta->keywords == '') {
                    $head .= '  <meta name="keywords" content="' . $xmb->data->meta->keywords . '" />' . PHP_EOL;
                } else {
                    $head .= '  <meta name="keywords" content="' . $xml[0]->meta->keywords . '" />' . PHP_EOL;
                }

                return $head;
            } else {
                // Loads external scripts
                if (file_exists(_CALSET_PATHS_BASE . _CALSET_DIRS_TEMPLATE . '/' . _CALSET_BASIC_TEMPLATE . '/basic.xml')) {
                    $xmb = simplexml_load_file(_CALSET_PATHS_BASE . _CALSET_DIRS_TEMPLATE . '/caloris-admin/basic.xml');
                }

                for ($a = 0; $a < count($xmb->data->scripts->files); $a++) {
                    if ($xmb->data->scripts->files["type"] == 'external') {
                        $head .= '  <script src="' . $xmb->data->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                    } else {
                        $head .= '  <script src="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $xmb->data->scripts->files[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                    }
                }

                $datatext = explode(";", $data["jscripts"]);

                if (count($data["jscripts"]) > 0) {
                    for ($a = 0; $a < count($datatext); $a++) {

                        if (substr($datatext[$a], 0, 7) == 'http://') {

                            $head .= '  <script src="' . $datatext[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        } else {
                            $head .= '  <script src="' . _CALSET_PATHS_URI . _CALSET_DIRS_EXTERNAL . '/' . $datatext[$a] . '" type="text/javascript"></script>' . PHP_EOL;
                        }
                    }
                }

                // Loads external styles
                for ($a = 0; $a < count($xmb->data->style->files); $a++) {
                    if ($xmb->data->style->files["type"] == 'external') {
                        $head .= '  <link rel="stylesheet" href="' . $xmb->data->style->files[$a] . '" type="text/css" media="screen,projection" />' . PHP_EOL;
                    } else {
                        $head .= '  <link rel="stylesheet" href="' . _CALSET_PATHS_URI . _CALSET_DIRS_TEMPLATE . '/caloris-admin/' . $xmb->data->style->files[$a] . '" type="text/css" media="screen,projection" />' . PHP_EOL;
                    }
                }

                $head .= '<title>' . $xmb->data->title->prefix . $data["title"] . $xmb->data->title->suffix . '</title>';
                $this->renderHeadAdmin = $head;
            }
        }

        function renderBody($templateFile = '') {
            if ($this->type == 'xml') {
                $head = $this->renderHead();
            } else {
                $head = $this->renderHeadAdmin;
            }

            if (isset($this->content2)) {
                $content2 = $this->content2;
            } else {
                $content2 = '';
            }

            $template = $this->loadTemplate($templateFile);
            $parseTemplate = $this->parse($template);
            $parseTemplate = preg_replace("/\[data\]/", $this->parse($head), $parseTemplate);
            $parseTemplate = preg_replace("/\[content2\]/", $this->parse($content2), $parseTemplate);
            return preg_replace("/\[content\]/", $this->parse($this->content), $parseTemplate);
        }

        function save($cachefile = '') {
            if (empty($cachefile)) {
                $path = _CALSET_PATHS_BASE . _CALSET_DIRS_CACHE . '/' . $this->name . '.html';
            } else {
                $path = _CALSET_PATHS_BASE . _CALSET_DIRS_CACHE . '/' . $cachefile . '.html';
            }

            $content .= $this->renderHead();
            $content .= $this->renderBody();

            echo $content;

            $file = fopen($path, 'w', 1);
            //fwrite($file, $content);
            //fclose($file);
            chmod($path, 0777);
        }

    }
}
